﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="DateTimeSettingDescriptorAttribute.cs" company="Radical Research Ltd">
//   Copyright (c) Radical Research Ltd. The MIT License (MIT)
// </copyright>
// <summary>
//   Describes a DateTime setting.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace RadicalResearch.MiniState.Attributes
{
    using System;
    using System.Reflection;

    using RadicalResearch.MiniState.Descriptors;

    /// <summary>Describes a DateTime setting.</summary>
    public class DateTimeSettingDescriptorAttribute : SettingDescriptorAttribute
    {
        #region Constants and Fields

        /// <summary>
        ///   Epoch year
        /// </summary>
        private readonly int epochYear;

        /// <summary>
        ///   Flag if the epoch year has been set.
        /// </summary>
        private readonly bool isEpochYearSet;

        #endregion

        #region Constructors and Destructors

        /// <summary>Initializes a new instance of the <see cref="DateTimeSettingDescriptorAttribute"/> class.</summary>
        /// <param name="epochYear">The epoch year.</param>
        public DateTimeSettingDescriptorAttribute(int epochYear)
        {
            this.epochYear = epochYear;
            this.isEpochYearSet = true;
        }

        /// <summary>Initializes a new instance of the <see cref="DateTimeSettingDescriptorAttribute"/> class.</summary>
        /// <param name="isValidated">if set to <c>true</c> the setting is validated with hash validation.</param>
        /// <param name="epochYear">The epoch year.</param>
        public DateTimeSettingDescriptorAttribute(bool isValidated, int epochYear)
            : base(isValidated)
        {
            this.epochYear = epochYear;
            this.isEpochYearSet = true;
        }

        /// <summary>Initializes a new instance of the <see cref="DateTimeSettingDescriptorAttribute"/> class.</summary>
        /// <param name="settingKey">The setting key.</param>
        /// <param name="isValidated">if set to <c>true</c> the setting is validated with hash validation.</param>
        /// <param name="epochYear">The epoch year.</param>
        public DateTimeSettingDescriptorAttribute(string settingKey, bool isValidated, int epochYear)
            : base(settingKey, isValidated)
        {
            this.epochYear = epochYear;
            this.isEpochYearSet = true;
        }

        /// <summary>Initializes a new instance of the <see cref="DateTimeSettingDescriptorAttribute"/> class.</summary>
        /// <param name="settingKey">The setting key.</param>
        /// <param name="valueKey">The value key.</param>
        /// <param name="isValidated">if set to <c>true</c> the setting is validated with hash validation.</param>
        /// <param name="epochYear">The epoch year.</param>
        public DateTimeSettingDescriptorAttribute(string settingKey, string valueKey, bool isValidated, int epochYear)
            : base(settingKey, valueKey, isValidated)
        {
            this.epochYear = epochYear;
            this.isEpochYearSet = true;
        }

        /// <summary>
        ///   Initializes a new instance of the <see cref = "DateTimeSettingDescriptorAttribute" /> class.
        /// </summary>
        public DateTimeSettingDescriptorAttribute()
        {
            this.isEpochYearSet = false;
        }

        /// <summary>Initializes a new instance of the <see cref="DateTimeSettingDescriptorAttribute"/> class.</summary>
        /// <param name="settingKey">The setting key.</param>
        /// <param name="isValidated">if set to <c>true</c> the setting is validated with hash validation.</param>
        public DateTimeSettingDescriptorAttribute(string settingKey, bool isValidated)
            : base(settingKey, isValidated)
        {
            this.isEpochYearSet = false;
        }

        /// <summary>Initializes a new instance of the <see cref="DateTimeSettingDescriptorAttribute"/> class.</summary>
        /// <param name="settingKey">The setting key.</param>
        /// <param name="valueKey">The value key.</param>
        /// <param name="isValidated">if set to <c>true</c> the setting is validated with hash validation.</param>
        public DateTimeSettingDescriptorAttribute(string settingKey, string valueKey, bool isValidated)
            : base(settingKey, valueKey, isValidated)
        {
            this.isEpochYearSet = false;
        }

        #endregion

        #region Properties

        /// <summary>
        ///   Gets the epoch year.
        /// </summary>
        protected int EpochYear
        {
            get
            {
                return this.epochYear;
            }
        }

        #endregion

        #region Methods

        /// <summary>Gets the descriptor.</summary>
        /// <param name="property">The property.</param>
        /// <returns>Setting descriptor for the specified property.</returns>
        internal override SettingDescriptorBase GetDescriptor(PropertyInfo property)
        {
            if (!typeof(DateTime).IsAssignableFrom(property.PropertyType))
            {
                throw new SettingStoreException("Property must be assignable to a DateTime");
            }

            if (this.isEpochYearSet)
            {
                return new DateTimeSettingDescriptor(this.ValueKey, this.IsValidated, this.EpochYear);
            }

            return new DateTimeSettingDescriptor(this.ValueKey, this.IsValidated);
        }

        #endregion
    }
}